'''
Created on Apr 25, 2011

@author: Igor
'''

from challenge_helper import get_challenge_name, get_challenge_level, put_blinds, \
    game_setup, add_bid, betting_round_finished, generate_choices, Decision, \
    modify_last_bid, get_winner
from common import BaseRequestHandler
from computer_logic import make_move
from datetime import datetime
from google.appengine.api import users
from google.appengine.api.users import User
from lib.dbobjects import Profiler, Game, PrevHand


class Challenge(BaseRequestHandler):
    '''
    This is a one-on-one texas hold'em game
    '''
    def get(self, prev_hand=None, result_message=None):
        if (users.is_current_user_admin()):
            self.redirect('/admin')
        else:
            # Get the guest object for the current user
            profilers_query = Profiler.all().filter("user =",
                    users.get_current_user()).order('-modified')
            profiler = profilers_query.get()
            challenge_name = get_challenge_name(get_challenge_level(
                    profiler.money))
            template_values = {'challenge_name': challenge_name,
                               'profiler': profiler,
                               'prev_hand': prev_hand,
                               'result_message': result_message}
            self.generate('challenge.html', template_values)
    
    def setup_preflop(self, game, prev_hand=None):
        # Check if the challenge is over
        if game.my_money == 0:
            result_message = "The challenge is over. You won!"
            profilers_query = Profiler.all().filter("user =",
                    users.get_current_user()).order('-modified')
            profiler = profilers_query.get()
            profiler.money += game.your_money
            game.your_money = 0
            profiler.challenges[game.challenge_level] += 1
            profiler.put()
            game.put()
            self.get(prev_hand, result_message)
            return
        if game.your_money == 0:
            result_message = "The challenge is done. You lost."
            casino_query = Profiler.all().filter("user =", 
                    User("Casino")).order('-modified')
            casino = casino_query.get()
            casino.money += game.my_money
            game.my_money = 0
            profilers_query = Profiler.all().filter("user =",
                    users.get_current_user()).order('-modified')
            profiler = profilers_query.get()
            profiler.challenges[game.challenge_level] += 1
            profiler.put()
            casino.put()
            game.put()
            self.get(prev_hand, result_message)
            return
        # Increment the deal
        game.hand_number += 1
        game.i_deal = not game.i_deal
        # Starting the new deal, reset the values
        game.modified = datetime.now()
        game.round = 1
        game.preflop_bids = []
        game.flop_bids = []
        game.turn_bids = []
        game.river_bids = []
        game.all_in = False
        game.round_over = False
        game.my_cards = []
        game.table_cards = []
        game.your_cards = []
        game.message = ""
        game.debug = ""
        
        game_setup(game)
        put_blinds(game)
        if game.all_in:
            self.end_hand(game)
        else:
            self.start_round(game, prev_hand)

    # This function is called in the following situations:
    # 1. ALL_IN
    # 2. Someone FOLDED
    # 3. Reached the show down
    def end_hand(self, game, winner=None):
        prev_hand_query = PrevHand.all().filter("user =", 
                users.get_current_user()).order('-modified')
        prev_hand = prev_hand_query.get()
        if prev_hand is None:
            prev_hand = PrevHand(user=users.get_current_user())
        prev_hand.debug = game.debug
        prev_hand.your_images = [
                '/images/card_%s.png' % game.your_cards[0],
                '/images/card_%s.png' % game.your_cards[1]]
        if winner is not None:
            prev_hand.my_images = ['/images/card_back.png',
                    '/images/card_back.png']
            prev_hand.table_images = []
            if game.round in (2, 3, 4):
                for i in xrange(game.round + 1):
                    prev_hand.table_images.append('/images/card_%s.png' %
                                                  game.table_cards[i])
            if winner > 0:
                game.your_money += game.pot_money
                prev_hand.result_message = "I FOLDED, the pot(%d) is yours" \
                        % (game.pot_money - game.balance)
                game.pot_money = 0
            elif winner < 0:
                game.my_money += game.pot_money
                prev_hand.result_message = "You FOLDED, I get the pot(%d)" \
                        % (game.pot_money + game.balance)
                game.pot_money = 0
            else:
                print "What is this winner value? %d" % winner
                raise
        else:
            result = get_winner(game)
            prev_hand.table_images = []
            for i in xrange(5):
                prev_hand.table_images.append('/images/card_%s.png' %
                                              game.table_cards[i])
            prev_hand.my_images = ['/images/card_%s.png' %
                        game.my_cards[0], '/images/card_%s.png' %
                        game.my_cards[1]]
            if result > 0:
                prev_hand.result_message = "Congrats, you won!  " \
                        "You get the pot(%d)" % (game.pot_money)
                game.your_money += game.pot_money
                game.pot_money = 0
            elif result < 0:
                prev_hand.result_message = "Too bad, you lost the pot(%d)" \
                        % (game.pot_money)
                game.my_money +=game.pot_money
                game.pot_money = 0
            else:
                prev_hand.result_message = "It's a tie. We split the pot(%d)"\
                        % (game.pot_money)
                your_share = int(game.pot_money / 2)
                game.your_money += your_share
                game.my_money += game.pot_money - your_share
                game.pot_money = 0
        game.round = 0
        game.put()
        prev_hand.put()
        self.setup_preflop(game, prev_hand)

    def start_round(self, game, prev_hand=None):
        # If I start, make a move
        if ((game.round == 1 and game.i_deal) or
            game.round in (2, 3, 4) and not game.i_deal):
            move = make_move(game)
            if move == Decision.FOLD:
                self.end_hand(game, 1)
                return
        game.put()
        
        if game.all_in:
            self.end_hand(game)
        else:
            choices = generate_choices(game)
            game.message += "It is your turn."
            self.display(game, choices, prev_hand)

    def answer(self, game):
        game.message = ""
        if game.all_in:
            print "Should never get to answer, we are ALL-IN!"
            raise
        play_bet = int(self.request.get('play_bet', None))
        # If FOLD
        if play_bet == -1:
            self.end_hand(game, -1)
            return
        # If CALL
        elif play_bet == 0:
            # Check if this is becoming an all-in
            if game.balance * -1 >= game.your_money:
                money_over = game.balance * -1 - game.your_money
                game.my_money += money_over
                game.pot_money -= money_over
                modify_last_bid(game, game.your_money)
                game.pot_money += game.your_money
                add_bid(game, game.your_money)
                game.your_money = 0
                game.balance = 0
                game.all_in = True
                self.end_hand(game)
                return
            else:
                if game.balance == 0:
                    add_bid(game, 0)
                else:
                    call_amount = game.balance * -1
                    game.your_money -= call_amount
                    add_bid(game, call_amount)
                    game.pot_money += call_amount
                    game.balance = 0
                game.round_over = betting_round_finished(game)
        # If BET
        elif play_bet == 1:
            bet_amount = self.request.get('bet_amount', None)
            if bet_amount is None:
                print "We are betting None?"
                raise
            else:
                bet_amount = int(bet_amount)
                if bet_amount > game.your_money:
                    print "You don't have that much money!"
                    raise
                elif bet_amount >= game.balance * -1 + game.big_blind or \
                        bet_amount == game.your_money:
                    add_bid(game, bet_amount)
                    game.your_money -= bet_amount
                    game.pot_money += bet_amount
                    game.balance += bet_amount
                else:
                    print "This amount is too small for a bet"
                    raise
        
        if not game.round_over:
            move = make_move(game)
            if game.all_in:
                self.end_hand(game)
                return
            if move == Decision.FOLD:
                self.end_hand(game, 1)
                return
        if game.round_over:
            if game.round == 4:
                self.end_hand(game)
                return
            elif game.i_deal:
                game.message += "  The betting round is over."
                game.round += 1
                game.round_over = False
            else:
                game.round += 1
                game.round_over = False
                self.start_round(game)
                return
        choices = generate_choices(game)
        game.message += "  It is your turn."
        game.put()
        self.display(game, choices)
        
    def post(self):
        # Look up game info and read the form values
        games_query = Game.all().filter("user =", 
                users.get_current_user()).order('-modified')
        game = games_query.get()
        
        stack = self.request.get('stack', None)
        if stack is not None:
            initial_money = int(stack)
            # The profiler just started playing
            casino_query = Profiler.all().filter("user =", 
                    User('Casino')).order('-modified')
            casino = casino_query.get()
            if casino is None:
                casino = Profiler(user = User("Casino"),
                        nickname = "Robert De Niro", money = 0)
            profiler_query = Profiler.all().filter("user =",
                    users.get_current_user()).order('-modified')
            profiler = profiler_query.get()
            if profiler is None or profiler.money < \
                    BaseRequestHandler.CHALLENGE_CUTOFF:
                self.redirect('/')
                return
            if game is None:
                game = Game(user = users.get_current_user())
                game.big_blind = 2
            else:
                # Distribute leftovers from the previous game
                casino.money += game.my_money + game.pot_money
                game.my_money = 0
                game.pot_money = 0
                profiler.money += game.your_money
                game.your_money = 0
            game.challenge_level = get_challenge_level(profiler.money)
            game.bet_amount = initial_money
            profiler.money -= initial_money
            game.your_money += initial_money
            casino.money -= initial_money
            game.my_money += initial_money
            profiler.put()
            casino.put()
            game.put()
            game.round = 0
        if game.round == 0:
            self.setup_preflop(game)
        elif game.round in (1, 2, 3, 4):
            self.answer(game)
        else:
            print "This means we are in an inconsistent state"
            
    def display(self, game, choices, prev_hand=None):
        my_images = []
        for i in xrange(2):
            my_images.append("/images/card_back.png")
        table_images = []
        if game.round > 1:
            for i in xrange(game.round + 1):
                table_images.append("/images/card_%s.png" %
                        game.table_cards[i])
        your_images = []
        for i in xrange(2):
            your_images.append("/images/card_%s.png" % game.your_cards[i])
        template_values = {'game': game,
                           'my_images': my_images,
                           'table_images': table_images,
                           'your_images': your_images,
                           'choices': choices,
                           'prev_hand': prev_hand,
                           'challenge_name': get_challenge_name(
                                    game.challenge_level)}
        self.generate('challenge_play.html', template_values)